# -*- coding: utf-8 -*-
import sys
import logging
import sqlalchemy
from lxml import etree
from xadmin.model import *
from xadmin.lib.base import *

log = logging.getLogger(__name__)

class ProductsController(BaseController):
    """REST Controller styled on the Atom Publishing Protocol"""
    # To properly map this controller, ensure your config/routing.py file has
    # a resource setup:
    #     map.resource('product', 'products')


    def index(self, format='html'):
        """GET /products: All items in the collection."""
        # url_for('products')
        c.products = Session.query(Product).all()
        response.headers['Content-Type'] = 'text/xml; charset=utf-8'
        return render('/products/list.mako')

    def listByProject(self, project):
        """GET /:project/products: All Products in a project."""
        # url_for('products_by_project')
        project = Session.query(Project).get(project)
        if project is not None:
            c.products = Session.query(Product).filter_by(project_id=project.id).all()
            response.headers['Content-Type'] = 'text/xml; charset=utf-8'
            return render('/products/list.mako')
        else:
            abort(404)

    def create(self):
        """POST /products: Create a new item."""
        # url_for('products')
        try:
            content = request.body.read(int(request.environ['CONTENT_LENGTH']))
            tree = etree.fromstring(content)
            project = tree.xpath('/product/project')[0].text
            project = Session.query(Project).get(project)
            product = self._createProduct(project.id, content)
            del response.headers['Content-Type']
            response.headers['Location'] = '/products/%s' % product.id
            response.status_code = 201
            return
        except:
            abort(400)

    def createByProject(self, project):
        """POST /products: Create a new item."""
        # url_for('create_products_by_project')
        try:
            content = request.body.read(int(request.environ['CONTENT_LENGTH']))
            if not content:
                content = request.params.get('xml')
            pr = self._createProduct(project, content)
            del response.headers['Content-Type']
            response.headers['Location'] = h.url_for('product', id=pr.id)
            response.status_code = 201
            return
        except sqlalchemy.exceptions.InvalidRequestError:
            abort(400)

    def new(self, format='html'):
        """GET /products/new: Form to create a new item."""
        # url_for('products')
        c.url = h.url_for('products')
        response.headers['Content-Type'] = 'text/xml; charset=utf-8'
        return render('/products/form.mako')

    def newByProject(self, project):
        """GET /products/new: Form to create a new item."""
        # url_for('new_product_by_project')
        c.project = project
        c.url = h.url_for('create_products_by_project', project=project)
        response.headers['Content-Type'] = 'text/xml; charset=utf-8'
        return render('/products/form.mako')

    def update(self, id):
        """PUT /products/id: Update an existing item."""
        # Forms posted to this method should contain a hidden field:
        #    <input type="hidden" name="_method" value="PUT" />
        # Or using helpers:
        #    h.form(h.url_for('product', id=ID),
        #           method='put')
        # url_for('product', id=ID)
        product = Session.query(Product).get(id)
        if product:
            try:
                content = request.body.read(int(request.environ['CONTENT_LENGTH']))
                tree = etree.fromstring(content)
                name = tree.xpath('/product/name')
                if name:
                    product.name = name[0].text
                description = tree.xpath('/product/description')
                if description:
                    product.description = description[0].text
                path = tree.xpath('/product/path')
                if path:
                    product.path = path[0].text
                type = tree.xpath('/product/type')
                if type:
                    product.type = type[0].text
                #Session.save(product)
                Session.commit()
                response.headers['Content-Type'] = 'text/xml; charset=utf-8'
                response.headers['Location'] = '/products/%s' % product.id
                return
            except:
                abort(400)
        else:
            abort(404)

    def delete(self, id):
        """DELETE /products/id: Delete an existing item."""
        # Forms posted to this method should contain a hidden field:
        #    <input type="hidden" name="_method" value="DELETE" />
        # Or using helpers:
        #    h.form(h.url_for('product', id=ID),
        #           method='delete')
        # url_for('product', id=ID)
        product = Session.query(Product).get(id)
        if product:
            Session.delete(product)
            Session.commit()
            return
        else:
            abort(404)

    def show(self, id, format='html'):
        """GET /products/id: Show a specific item."""
        # url_for('product', id=ID)
        c.product = Session.query(Product).get(id)
        if c.product:
            response.headers['Content-Type'] = 'text/xml; charset=utf-8'
            return render('/products/view.mako')
        else:
            abort(404)

    def edit(self, id, format='html'):
        """GET /products/id;edit: Form to edit an existing item."""
        # url_for('edit_product', id=ID)
        pass

    def _createProduct(self, project_id, data):
        try:
            project = Session.query(Project).get(project_id)
            if project:
                tree = etree.fromstring(data.encode("utf8"))
                name = tree.xpath('/product/name')[0].text
                description = tree.xpath('/product/description')[0].text
                path = tree.xpath('/product/path')[0].text
                type = tree.xpath('/product/type')[0].text
                product = Product(name, description, path, type)
                project.products.append(product)
                Session.save(product)
                Session.commit()
                return product
            else:
                abort(404)
        except:
            print "ERROR: ", sys.exc_info()[0]
            abort(400)
